﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Community.StaticAnalysis.Rules.Tests.Dummies
{
    /// <summary>
    /// A class that is used for analysis. Contains Examples 
    /// </summary>
    internal class ND2000SampleClass
    {
        public const string MethodNameContainsLocalThatIsNotDisposed = "MethodContainsLocalThatIsNotDisposed";
        public const string MethodNameContainsLocalThatIsDisposed = "MethodContainsLocalThatIsDisposed";
        public const string MethodNameReturnsADisposableObject = "MethodReturnsADisposableObject";
        public const string MethodNameContainsDisposableObjectOutParam = "MethodContainsDisposableObjectOutParam";
        public const string MethodNameReturnsObjectInsideTryBlock = "MethodReturnsObjectInsideTryBlock";
        public const string MethodNameThatHasADisposableObjectAsParam = "MethodThatHasADisposableObjectAsParam";
        public const string MethodNameThatHasAComplexFinally = "MethodThatHasAComplexFinally";
        public const string MethodNameContainsReturnsDisposableObjectWithIfElse = "MethodContainsReturnsDisposableObjectWithIfElse";
        public const string MethodNameContainsForEachThatReturnsObject = "MethodContainsForEachThatReturnsObject";
        public const string MethodNameContainsReturnsDisposableObjectWithSwitch = "MethodContainsReturnsDisposableObjectWithSwitch";
        public const string MethodNameContainsDisposableObjectRefParam = "MethodContainsDisposableObjectRefParam";
        public const string MethodNameCallsDisposeButNotInFinally = "MethodCallsDisposeButNotInFinally";
        public const string MethodNameCallConstructorWithoutStoringIt = "MethodCallConstructorWithoutStoringIt";
        public const string MethodNameCallsAMethodThatReturnsAObjectAndForgotToCallDispose = "MethodCallsAMethodThatReturnsAObjectAndForgotToCallDispose";
        public const string MethodNameAssignToAField = "MethodAssignToAField";
        public const string GetPropertyNameDoesNotDisposeObject = "GetPropertyDoesNotDisposeObject";


        public object GetPropertyDoesNotDisposeObject 
        {
            get {
                DisposableObject o = new DisposableObject();
                o.DummyMethod();

                return new object();
            }

            set {
            
            
            }
        }

        public DisposableObject MethodReturnsObjectInsideTryBlock()
        {
            DisposableObject o;
            try
            {
                o = new DisposableObject();
                return o;
            }
            finally
            {
                GetHashCode();
            }
        }

        public void MethodCallsAMethodThatReturnsAObjectAndForgotToCallDispose() 
        {
            MethodReturnsADisposableObject();
        }

        public IDisposable MethodContainsForEachThatReturnsObject()
        {
            for (int index = 0; index < 30; index++)
            {
                if (index == DateTime.Now.Day) { return new DisposableObject2(); }

            }

            return null;
        }

        public void MethodCallConstructorWithoutStoringIt() 
        {
            new DisposableObject();
        }

        public IDisposable MethodContainsReturnsDisposableObjectWithIfElse()
        {
            if (DateTime.Today.Day == 1)
            {
                return new DisposableObject();
            }
            else return new DisposableObject2();
        }

        public IDisposable MethodContainsReturnsDisposableObjectWithSwitch()
        {
            switch (DateTime.Now.Day)
            {
                case 1: return new DisposableObject2();
                default: return new DisposableObject();
            }
        }


        public void MethodThatHasADisposableObjectAsParam(DisposableObject o)
        {
            o.GetHashCode();
        }

        public void MethodContainsDisposableObjectRefParam(ref DisposableObject o)
        {
            o = new DisposableObject();
        }


        public void MethodContainsDisposableObjectOutParam(out DisposableObject o)
        {
            o = new DisposableObject();
        }

        public void MethodContainsLocalThatIsNotDisposed()
        {
            DisposableObject o = new DisposableObject();
            o.DummyMethod();
        }

        public void MethodCallsDisposeButNotInFinally() {
            DisposableObject o = new DisposableObject();
            o.Dispose();
        }

        public void MethodContainsLocalThatIsDisposed()
        {
            using (DisposableObject o = new DisposableObject())
            {
                
                GetType();
            }
        }

        public DisposableObject MethodReturnsADisposableObject()
        {
            return new DisposableObject();
        }

        public IDisposable _afield = null;
        public void MethodAssignToAField() {
            _afield = new DisposableObject2();
            _afield.Dispose();
        }

        public void MethodThatHasAComplexFinally()
        {
            DisposableObject complexScope1Good = null;
            try
            {
                complexScope1Good = new DisposableObject();

                DisposableObject complexScope2Good = null;
                try
                {
                    complexScope2Good = new DisposableObject();
                    DisposableObject complexScope3Bad;
                    GetType();
                    try
                    {
                        complexScope3Bad = new DisposableObject();


                        using (DisposableObject complexScope4Good = new DisposableObject())
                        {
                            complexScope3Bad.DummyMethod();
                        }
                    }
                    finally
                    {
                        Console.WriteLine();
                    }

                }
                finally
                {

                    if (complexScope2Good != null)
                        complexScope2Good.Dispose();
                }
            }

            finally
            {
                if (complexScope1Good != null)
                {
                    complexScope1Good.Dispose();
                }
            }
        }


      

    }
}
